import StateCodeMap from "@/utils/websocket/stateCodeMap";
import handleWSCmd from "@/utils/websocket/handleWSCmd";
import fso from "@/utils/FileOperate/operate";

import { listFailCmd } from "@/api/home";

import type { DeviceCmdType } from "@/typings/businessType";
import type { StateCodeMapKey } from "@/utils/websocket/stateCodeMap";
import { uploadData } from "@/api/websocket";

/** 处理离线指令 */
export const handleOffLineCmd = async (code: string) => {
  return new Promise<void | Error>(async resolve => {
    let errMsg = "";
    try {
      // 这些命令是可以离线执行的
      const cmds = [
        StateCodeMap.REMOVE_RESOURCE,
        StateCodeMap.SET_BRIGHTNESS,
        StateCodeMap.SET_SYS_TIME,
        StateCodeMap.SET_VOLUME,
        StateCodeMap.CLEAR_OLD_APP_RESOURCE
        // StateCodeMap.UPDATE_APP, // TODO 安装升级包时后没有修改升级指令的状态, 会导致无限升级的问题
      ].join(",");

      fso.info("查询离线指令: ", cmds);
      const offLineCmdDatas: DeviceCmdType[] = await listFailCmd(code, cmds).then(res => res.data);

      // 这里汇总出所有的指令
      const groupMapCmd = offLineCmdDatas.reduce((pre, cur) => {
        if (!pre[cur.cmd]) {
          pre[cur.cmd] = cur;
        } else {
          // 只取最大时间的数据(剩下的也要回传数据, 因为执行了最后的了)
          if (Number(cur.batchId) > Number(pre[cur.cmd].batchId)) {
            pre[cur.cmd] = cur;
          }
        }
        return pre;
      }, {} as { [k in StateCodeMapKey]: DeviceCmdType });

      if (offLineCmdDatas.length) {
        fso.info("查询到需要执行的的离线指令: ", offLineCmdDatas);
      }

      // @ts-ignore
      const keys: StateCodeMapKey[] = Object.keys(groupMapCmd);

      for (let i = 0; i < keys.length; i++) {
        const key = keys[i];
        const cmdItem = groupMapCmd[key];
        fso.info("执行离线指令", key, cmdItem);
        try {
          const data: any = JSON.parse(cmdItem.msg || "{}");
          await handleWSCmd({
            cmd: cmdItem.cmd,
            data,
            msg: "离线执行的指令"
          });
        } catch (err) {
          fso.error("离线指令执行失败了: ", err);
        }
      }

      // 把非当次执行的指令(就是说重复的旧指令都设置为已经执行)
      const ids = Object.values(groupMapCmd).map(e => e.id);
      if (ids.length) {
        const outmodedCmd = offLineCmdDatas.filter(e => !ids.includes(e.id));
        for (let i = 0; i < outmodedCmd.length; i++) {
          const outmodedCmditem = outmodedCmd[i];
          fso.info("过时指令直接回传数据", outmodedCmditem);

          const data: any = JSON.parse(outmodedCmditem.msg || "{}");
          uploadData({
            batchId: outmodedCmditem.batchId || "",
            deviceCode: code,
            cmd: String(outmodedCmditem.cmd),
            data: JSON.stringify({
              ...(data || {}),
              cmd: outmodedCmditem.cmd,
              backTime: Date.now() // 返回数据时间戳
            })
          })
            .then(res => {
              fso.info("过时指令回传数据响应: ", res.data);
            })
            .catch(err => {
              fso.error("过时指令数据回传失败", err);
            });
        }
      }
    } catch (err) {
      console.log("err: ", err);
      errMsg = `${err}`;
    } finally {
      resolve(errMsg ? new Error(errMsg) : undefined);
    }
  });
};
